﻿/* dk2Repository - Copyright (C) 2011 Daniel Kuczewski http://www.dk2.de/

 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */

using System;
using System.Collections.Generic;
using System.Data;
using dk2Database.Interfaces;

namespace dk2Database
{
    /// <summary>
    /// Stores and executes multiple commands in a transaction. 
    /// </summary>
    public class TransactionInvoker : ICommandInvoker, IConnectionFactory, IDisposable
    {
        private readonly Database _db;
        private List<ICommand> _cmds;

        private IConnection _con;
        private IDbTransaction _trans;

        public TransactionInvoker() : this(Databases.Default)
        {
            
        }

        public TransactionInvoker(Database db)
        {
            _db = db;
            _cmds = new List<ICommand>();
        }

        public void AddCommand(ICommand cmd)
        {
            _cmds.Add(cmd);
        }

        public void AddCommands(IEnumerable<ICommand> cmds)
        {
            _cmds.AddRange(cmds);
        }

        public void Execute()
        {

            try
            {
                using (_con = _db.CreateConnection())
                {
                    using (_trans = _con.Connection.BeginTransaction())
                    {
                        foreach (var cmd in _cmds)
                        {
                            cmd.ConnectionFactory = this;
                            cmd.Execute();
                        }

                        _trans.Commit();
                    }
                }
            }
            catch (Exception)
            {
                if(_trans !=null)
                    _trans.Rollback();

                throw;
            }

        }

        public IConnection CreateConnection()
        {
            return new TransactionalConnection(_trans);
        }

        public void Dispose()
        {
            
        }
    }
}
